import {defineStore} from 'pinia';

/**
 * curl为简单模块增删改查的基类，该类需要配合后端进行调整
 * columns 为表格列 具体字段有width title field等
 * options 为操作区 具体字段有title emit enabled等
 * searchForm 为查询表单 具体字段有title, type field 等
 */
class Curl{
    id = null;
    name = "";
    table = null;
    pageNo = 1;
    pageSize = 10;
    total = 0;
    condition = {};
    defaultCondition = {};
    sort = {};
    columns = [];
    options = [];
    searchForm = [];
    api = {};
    form = null;
    view = null;
    dataList = [];
    isTree = false;
    constructor(id, columns, options, searchForm, api, isTree) {
        this.id = id;
        this.columns = columns;
        this.options = options;
        this.searchForm = searchForm;
        this.api = api;
        this.isTree = isTree;
    }

    /**
     * 创建表格
     * @param table x-table的ref
     */
    createTable(table, name){
        if(! table) {
            return;
        }

        this.name = name;
        this.table = table.value;
        this.table.setColumns(this.columns);
        this.table.setSearchForm(this.searchForm);
        this.table.setOptions(this.options);
        return this;
    }

    removeColumn(field) {
        let idx = this.columns.findIndex(x => x.field == field);
        if(idx > -1) {
            this.columns.splice(idx, 1);
            this.table.setColumns(this.columns);
        }
    }

    addColumn(column, index) {
        if(Helper.empty(column) || Helper.empty(column.field)) {
            return;
        }
        let idx = this.columns.findIndex(x => x.field == column.field);
        if(idx == -1) {
            this.columns.splice(index, 0, column);
            this.table.setColumns(this.columns);
        }
    }

    async openCreate(){
        let op = this.createOpen(CURL.CREATE, {});

        op.confirm(c => {
            c.validate(async (form) => {
                if(form) {
                    let result = await this.save(form);
                    if(result){
                        Dialog.close();
                    }
                }
            });
        })
        return op;
    }

    async openModify(params) {
        let op = this.createOpen(CURL.MODIFY, {});
        op.mounted(async c => {
            let data = await this.getInfo(params);
            if(! data) {
                return;
            }
            c.render(data, CURL.MODIFY);
        })
        op.confirm(c => {
            c.validate(async (form) => {
                if(form) {
                    let result = await this.modify(form);
                    if(result){
                        Dialog.close();
                    }
                }
            });
        })
        return op;

    }

    openView(params){
        let op = this.createOpen(CURL.VIEW, {});
        op.mounted(async c => {
            let data = await this.getInfo(params);
            if(! data) {
                return;
            }
            c.render(data, CURL.VIEW);
        })

        op.setConfirmText(false);
        return op;
    }

    clearDefaultCondition() {
        this.defaultCondition = {};
    }

    removeDefaultCondition(field) {
        delete this.defaultCondition[field];
    }

    load(defaultCondition = {}){
        this.defaultCondition = defaultCondition;
        if(this.isTree) {
            this.getTree()
        } else {
            this.getList(1, 10);
        }

        return this;
    }

    /**
     * 创建form表单
     * @param component
     */
    setView(component) {
        this.view = component;
        return this;
    }

    /**
     * 创建form表单
     * @param component
     */
    setForm(component) {
        this.form = component;
        return this;
    }

    /**
     * 查询事件触发
     * @param pageNo
     * @param pageSize
     * @param condition
     * @param sort
     */
    search(pageNo, pageSize, condition, sort) {
        if(this.isTree) {
            if(Helper.emptyJson(condition)) {
                this.table.setData(this.dataList);
                return;
            }

            let dataList = Helper.findArray(this.dataList, condition);
            this.table.setData(dataList);
        } else {
            this.getList(pageNo, pageSize, condition, sort);
        }

    }

    /**
     * 刷新事件触发，比如保存成功后触发等等
     */
    refresh() {
        if(this.isTree) {
            this.getTree();
        } else {
            this.search(this.pageNo, this.pageSize, this.condition, this.sort);
        }
    }

    /**
     * 调用 tree列表接口
     * @param pageNo
     * @param pageSize
     * @param condition
     * @param sort
     * @returns {Promise<void>}
     */
    async getTree(condition) {
        this.condition = condition;

        //todo 参数处理
        let params = {}

        if(condition) {
            params = Object.assign(params, condition);
        }

        params = Object.assign(params, this.defaultCondition);
        //todo 调用接口，加载数据
        if(this.table) {
            this.table.isLoading(true)
        } else {
            Msg.loading("加载中...");
        }

        let {code, data} = await Http.get(this.api.LIST, params);
        if(this.table) {
            this.table.isLoading(false)
        } else {
            Msg.loading(false);
        }

        this.dataList = data;
        if(this.table) {
            this.table.setData(this.dataList);
        }
    }

    /**
     * 调用 list列表接口
     * @param pageNo
     * @param pageSize
     * @param condition
     * @param sort
     * @returns {Promise<void>}
     */
    async getList(pageNo, pageSize, condition, sort) {
        this.pageNo = pageNo;
        this.pageSize = pageSize;
        this.condition = condition;
        this.sort = sort;

        //todo 参数处理
        let params = {}
        params.pageNo = pageNo;
        params.pageSize = pageSize;

        if(condition) {
            params = Object.assign(params, condition);
        }

        params = Object.assign(params, this.defaultCondition);

        if(sort) {
            params.sort = sort;
        }

        //todo 调用接口，加载数据
        if(this.table) {
            this.table.isLoading(true)
        } else {
            Msg.loading("加载中...");
        }

        let api = this.api.LIST;
        let result = {};
        if(typeof api == 'object') {
            result = await Http[api.method](api.api, params);
        } else {
            result = await Http.get(api, params);
        }

        let code = result.code;
        let data = result.data;
        if(this.table) {
            this.table.isLoading(false)
        } else {
            Msg.loading(false);
        }

        this.dataList = data.records;
        this.pageNo = data.current;
        this.pageSize = data.size;
        this.total = data.total;
        if(this.table) {
            this.table.setData(this.dataList);
            this.table.setPagination(this.pageNo, this.pageSize, this.total);
        }
    }

    /**
     * 调用详情接口
     * @param params
     * @returns {Promise<*>}
     */
    async getInfo(params, method = 'get') {
        Msg.loading("加载中...")
        let {code, data} = await Http[method](this.api.INFO, typeof params != 'object' ? {id: params} : params);
        Msg.loading(false)
        if(code != 200) {
            return false;
        }
        return data;
    }

    /**
     * 调用保存接口
     * @param formData
     * @returns {Promise<boolean>}
     */
    async save(formData) {
        Msg.loading("提交中...")
        let result = await Http.post(this.api.SAVE, formData);
        Msg.loading(false);

        if(result.code != 200) {
            Msg.error("保存失败");
            return false;
        }

        Msg.success("保存成功");
        this.refresh();
        return true;
    }

    async modify(formData) {
        Msg.loading("提交中...")
        let modifyApi = this.api.MODIFY;
        let result = {};
        if(typeof modifyApi == 'object') {
            result = await Http[modifyApi.method](modifyApi.api, formData);
        } else {
            result = await Http.post(this.api.MODIFY, formData);
        }
        Msg.loading(false);
        if(result.code != 200) {
            Msg.error("修改失败");
            return false;
        }

        Msg.success("修改成功");
        this.refresh();
        return true;
    }

    async remove(params) {
        Msg.confirm("您确认删除该条数据吗？").then(async _ => {
            let api = this.api.REMOVE;
            let result = {};
            if(typeof api == 'object') {
                result = await Http[api.method](api.api, typeof params != 'object' ? {id: params} : params);
            } else {
                result = await Http.post(api, typeof params != 'object' ? {id: params} : params);
            }
            if(result.code != 200) {
                Msg.error("删除失败");
                return false;
            }
            Msg.success("删除成功");
            this.refresh();
            return true;
        })
    }

    open(type, data, options = {}) {
        let op = this.createOpen(type, options)
            .setWidth(Helper.empty(options.width) ? 800 : options.width)
            .setProps(options.props);
        op.mounted(c => {
            c.render(data, type);
        })

        op.confirm(c => {
            c.validate(async (form) => {
                if(form) {
                    let result = false;
                    if(CURL.MODIFY == type) {
                        result = await this.modify(form);
                    } else {
                        result = await this.save(form);
                    }

                    if(result){
                        Dialog.close();
                    }
                }
            });
        })
        console.log("123", type, CURL.VIEW)
        if(CURL.VIEW == type) {
            op.setConfirmText(false);
        }
        return op;
    }

    createOpen(type, options) {
        let title = options.title;
        let component = this.form;
        if(Helper.empty(title)) {
            if(type == CURL.VIEW) {
                title = "详情";
            } else if(type == CURL.MODIFY){
                title = "修改";
            } else if(type == CURL.CREATE) {
                title = "新增";
            }
        }
        if(! Helper.empty(this.view) && type == CURL.VIEW) {
            component = this.view;
        }
        title = Helper.empty(this.name) ? title : this.name + title;
        let op = Dialog.open(component, title)
        return op;
    }

    useStore() {
        let getters = {};
        let state = {};
        let actions = {};
        //todo 获取父类getters
        Object.keys(Curl.prototype).forEach(e => getters[e] = Curl.prototype[e].bind(this));
        //todo 获取子类getters
        Object.keys(this.constructor.prototype).forEach(e => getters[e] = this.constructor.prototype[e].bind(this));
        //todo 获取父类actions
        Reflect.ownKeys(Curl.prototype).filter(e => e != 'constructor' && e != 'useStore' && !getters[e]).forEach(e => actions[e] = Curl.prototype[e].bind(this));
        //todo 获取子类action
        Reflect.ownKeys(this.constructor.prototype).filter(e => e != 'constructor' && !getters[e]).forEach(e => actions[e] = this.constructor.prototype[e].bind(this));
        //todo 获取state 暂定开放 && e != 'columns' && e != 'options' && e != 'searchForm' && e != 'api'
        let filter = ['id', 'table', 'form', 'ADD', 'MODIFY', 'VIEW'];
        Object.keys(this).filter(e => filter.indexOf(e) > -1).forEach(e => state[e] = this[e]);

        let store = defineStore({
            id: this.id,
            state() {
                return state;
            },
            getters: getters,
            actions: actions,
        })

        return store();
    }
}

export function curlStore(id, columns, options, searchForm, api, config, isTree) {
    let curl = new Curl(id, columns, options, searchForm, api, isTree);
    let getters = {};
    let state = {};
    let actions = {};
    //todo 获取父类getters
    Object.keys(Curl.prototype).forEach(e => getters[e] = Curl.prototype[e].bind(curl));
    //todo 获取父类actions
    Reflect.ownKeys(Curl.prototype).filter(e => e != 'constructor' && e != 'useStore' && !getters[e]).forEach(e => actions[e] = Curl.prototype[e].bind(curl));
    //todo 获取state 暂定开放 && e != 'columns' && e != 'options' && e != 'searchForm' && e != 'api'
    let filter = ['id', 'table', 'form'];
    Object.keys(curl).filter(e => filter.indexOf(e) > -1).forEach(e => state[e] = curl[e]);

    let baseConfig = {
        state,getters,actions
    }

    config.state = config.state();

    Helper.mergeJson(baseConfig, config);
    let store = defineStore({
        id: id,
        state() {
            return baseConfig.state;
        },
        getters: baseConfig.getters,
        actions: baseConfig.actions
    })

    return store;
}

export default Curl
